# -*- coding: utf-8 -*-
# @Date：2024/9/30 14:21:53
# @Author：CJiaの青姝
# @FileName：register
# @Editor：PyCharm2024
# @Remark：
import re
import bcrypt
from typing import Any
from typing_extensions import Self

from django.core.cache import cache
from backend.settings import TOKEN_LIFETIME
from auths.regular import password_reg, email_reg
from auths.models import User
from ninja import Router, ModelSchema

from utils.cj_bcrypt import encrypt_pass
from utils.cj_response import SuccessResponse, ErrorResponse

router = Router()


class RegisterSchemaIn(ModelSchema):

    def model_validate(
            cls,
            obj: Any,
            *,
            strict: bool | None = None,
            from_attributes: bool | None = None,
            context: Any | None = None,
    ) -> Self:
        if obj.username.strip() == '' or obj.username.strip() is None:
            return "用户名不能为空", 400
        elif obj.email.strip() == '' or obj.email.strip() is None:
            return "邮箱不能为空", 400
        elif obj.password.strip() == '' or obj.password.strip() is None:
            return "密码不能为空", 400
        if not re.match(password_reg, obj.password.strip()):
            return "密码强度等级不够", 400
        elif not re.match(email_reg, obj.email.strip()):
            return "邮箱格式不正确", 400
        # 判断重复
        if User.objects.filter(email=obj.email).exists():
            return "邮箱已存在，请重新输入", 400
        # 返回请求数据
        return obj.dict(), 200

    class Config:
        title = '用户注册参数'
        model = User
        model_fields = ["username", "email", "password"]


class RegisterSchemaOut(ModelSchema):
    class Config:
        title = '用户对象实例'
        model = User
        model_exclude = ["password", "password_decrypt", "salt"]


@router.post("/register", auth=None, response=RegisterSchemaOut, summary="用户注册")
def register(request: Any, data: RegisterSchemaIn) -> SuccessResponse | ErrorResponse:
    """ 用户注册 """
    message, code = data.model_validate(data)
    if code == 400:
        return ErrorResponse(msg=message)
    # 生成密匙 -> 默认字节
    salt = bcrypt.gensalt(rounds=10)
    message['salt'] = salt.decode()
    # 密码加密
    message['password_decrypt'] = message['password']
    message['password'] = encrypt_pass(message['password_decrypt'], salt)
    # 初始化
    message['usageNumber'] = 0
    message['total'] = 10000
    # 保存数据
    user = User.objects.create(**message)
    # 保存成功后缓存该用户加密盐(时效24小时)
    cache.set(user.email + "_salt", user.salt, TOKEN_LIFETIME)
    # 返回结果
    return user
